package com.org.msmvc.sys.dao.common;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import net.sf.ezmorph.object.DateMorpher;
import net.sf.json.JSONObject;
import net.sf.json.util.JSONUtils;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * 处理实体类的工具
 * 
 * @author zsh
 *
 */
public class EntityUtil {
	private static Log log = LogFactory.getLog(EntityUtil.class);
	public static String dtPattern = "yyyy-MM-dd HH:mm";
	private static String domainPath = "com.org.msmvc.entity";
	public static String tablePrefix = "jtx_";
	private static DateMorpher dateMorpher = null;

	// 根据类名创建对象
	public static Object getEntity(String className)
			throws InstantiationException, IllegalAccessException, ClassNotFoundException {
		return Class.forName(domainPath + className).newInstance();
	}

	// 根据类名创建Class
	public static Class<?> getClass(String className) throws ClassNotFoundException {
		return Class.forName(domainPath + className);
	}

	// 将json转换为对象,同时将json里面的属性表添加到fields中
	public static Object toBean(String className, String json, Collection<String> fields) throws Exception, Exception {
		// 将json字符串转换为对象
		Class<?> clazz;
		try {
			clazz = EntityUtil.getClass(className);
		} catch (ClassNotFoundException e1) {
			throw new Exception("指定的对象不存在：" + className);
		}
		// json里面的时间格式
		if (dateMorpher == null) {
			dateMorpher = new DateMorpher(new String[] { EntityUtil.dtPattern });
			JSONUtils.getMorpherRegistry().registerMorpher(dateMorpher);
		}
		Object entity;
		// json
		if (json.startsWith("{")) {
			// 将json转换为对象
			JSONObject jsonObject = JSONObject.fromObject(json);
			entity = JSONObject.toBean(jsonObject, clazz);
			// 取得所有属性，便于在下面清除实际不存在的属性
			Collection<String> allFields = EntityUtil.getNeedStoreFieldNames(entity);
			// 取得json里面的属性表
			Iterator<String> keyIter = jsonObject.keys();
			while (keyIter.hasNext()) {
				String key = keyIter.next();
				if (allFields.contains(key)) {
					fields.add(key);
				}
			}
			// 将Entity类型的id，转换为对象
			Map<String, Field> entityFields = EntityUtil.getEntityFields(entity, fields);
			for (String key : entityFields.keySet()) {
				Class entityClass = entityFields.get(key).getType();
				try {
					Entity value = (Entity) entityClass.newInstance();
					int id = jsonObject.getInt(key);
					value.setId(id);
					EntityUtil.setValue(entity, key, value);
				} catch (InstantiationException e) {
					log.error(e.getMessage());
				} catch (IllegalAccessException e) {

				}
			}
		} else {
			throw new Exception("数据格式异常，请提供json格式");
		}
		return entity;
	}

	// 取得id，如果没有getId()这个方法，则返回0
	public static int getId(Object entity) {
		try {
			Method method = entity.getClass().getMethod("getId");
			try {
				return Integer.parseInt(method.invoke(entity, null) + "");
			} catch (IllegalArgumentException e) {
				log.error(e.getMessage());
			} catch (IllegalAccessException e) {
				log.error(e.getMessage());
			} catch (InvocationTargetException e) {
				log.error(e.getMessage());
			}
		} catch (SecurityException e) {

		} catch (NoSuchMethodException e) {

		}
		return 0;
	}

	// 设置指定属性的值
	public static void setValue(Object entity, String fieldName, Object value) {
		try {
			Method method = getWriteMethod(entity.getClass(), fieldName, value.getClass());
			try {
				method.invoke(entity, value);
			} catch (IllegalArgumentException e) {
				log.error(e.getMessage());
			} catch (IllegalAccessException e) {
				log.error(e.getMessage());
			} catch (InvocationTargetException e) {
				log.error(e.getMessage());
			}
		} catch (SecurityException e) {

		} catch (NoSuchMethodException e) {

		} catch (Exception e) {

		}
	}

	// 取得指定属性的值
	public static Object getValue(Object entity, String fieldName) {
		try {
			Method method = getReadMethod(entity.getClass(), fieldName);
			try {
				Object value = method.invoke(entity, null);
				if (value instanceof Entity) {
					// 如果是实体类，保存id即可
					return ((Entity) value).getId();
				}
				return value;
			} catch (IllegalArgumentException e) {
				log.error(e.getMessage());
			} catch (IllegalAccessException e) {
				log.error(e.getMessage());
			} catch (InvocationTargetException e) {
				log.error(e.getMessage());
			}
		} catch (SecurityException e) {

		} catch (NoSuchMethodException e) {

		} catch (Exception e) {

		}
		return null;
	}

	// 取得属性的get操作
	private static Method getReadMethod(Class theClass, String fieldName) throws Exception {
		String field = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
		try {
			return theClass.getMethod(field);
		} catch (NoSuchMethodException e) {
			// 没有定义theClass = theClass.getSuperclass();
		} catch (SecurityException e) {
			throw new Exception("安全原因：" + e.getMessage());
		}
		return null;
	}

	// 取得属性的set操作
	private static Method getWriteMethod(Class theClass, String fieldName, Class clazz) throws Exception {
		String field = "set" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
		try {
			return theClass.getMethod(field, clazz);
		} catch (NoSuchMethodException e) {
			// 没有定义
			if (clazz.equals(Double.class)) {
				clazz = double.class;
				return theClass.getMethod(field, clazz);
			} else if (clazz.equals(Integer.class)) {
				clazz = int.class;
				return theClass.getMethod(field, clazz);
			} else if (clazz.equals(Long.class)) {
				clazz = long.class;
				return theClass.getMethod(field, clazz);
			}
		} catch (SecurityException e) {
			throw new Exception("安全原因：" + e.getMessage());
		}
		return null;
	}

	/**
	 * 取得数据库表名 如果输入的对象提供了getTableName的方法，则使用该方法返回的值作为表名。 否则使用table_类名的方式
	 * 
	 * @return java.lang.String
	 */
	public static String getTableName(Object entity) {
		Object value = null;
		try {
			// 优先调用getTableName的方法，则使用该方法返回的值作为表名
			Method method = entity.getClass().getMethod("getTableName");
			try {
				value = method.invoke(entity, null);
			} catch (IllegalArgumentException e) {
				log.error(e.getMessage());
			} catch (IllegalAccessException e) {
				log.error(e.getMessage());
			} catch (InvocationTargetException e) {
				log.error(e.getMessage());
			}
		} catch (SecurityException e) {

		} catch (NoSuchMethodException e) {
			// 没有提供getTableName的方法将使用table_类名的方式
		}
		if (value != null) {
			return value + "";
		} else {
			// 使用table_类名的方式
			String fullName = entity.getClass().getName();
			return EntityUtil.tablePrefix + fullName.substring(fullName.lastIndexOf(".") + 1);
		}
	}

	/**
	 * 取得需要保存的属性名称 在取得数据的时候，如果没有指定需要哪些属性，将调用该方法取得所有的属性
	 * 声明为transient或final或者static的成员将不在返回之列
	 */
	public static Collection<String> getNeedStoreFieldNames(Object entity) {
		Collection<Field> fields = getNeedStoreFields(entity);
		Collection<String> fieldNames = new ArrayList<String>();
		for (Field field : fields) {
			if (!"id".equals(field.getName())) {
				fieldNames.add(field.getName());
			}
		}
		return fieldNames;
	}

	/*
	 * 取得对象类型的属性
	 */
	public static Map<String, Field> getEntityFields(Object entity, Collection<String> fields) {
		Map<String, Field> rs = new HashMap<String, Field>();
		Class theClass = entity.getClass();
		if (fields == null) {
			// 取得全部属性及类型
			Field[] allFields;
			String modifier = "";
			while (theClass != null) {
				allFields = theClass.getDeclaredFields();
				for (int i = 0; i < allFields.length; i++) {
					Field f = allFields[i];
					modifier = Modifier.toString(f.getModifiers());
					if (modifier.indexOf("transient") < 0 && modifier.indexOf("final") < 0
							&& modifier.indexOf("static") < 0
					// && this.isDBFieldType(allFields[i].getType().getName())
					) {
						if (Entity.class.isAssignableFrom(f.getType())) {
							rs.put(f.getName(), f);
						}
					}
				}
				theClass = theClass.getSuperclass();
			}
		} else {
			// 从可选属性中查找
			for (String name : fields) {
				Field f;
				try {
					f = entity.getClass().getDeclaredField(name);
					if (Entity.class.isAssignableFrom(f.getType())) {
						rs.put(name, f);
					}
				} catch (SecurityException e) {
					log.error(e.getMessage());
				} catch (NoSuchFieldException e) {

				}
			}
		}
		return rs;
	}

	// 需要保存的全部的属性
	private static Map<Class, Collection<Field>> needStoreFields = new HashMap<Class, Collection<Field>>();

	/**
	 * 取得需要保存的属性 声明为transient或final或者static的成员将不在返回之列
	 */
	private static Collection<Field> getNeedStoreFields(Object entity) {
		Collection<Field> fields = needStoreFields.get(entity.getClass());
		if (fields == null) {
			// 取得全部属性及类型
			fields = new ArrayList<Field>();
			Class theClass = entity.getClass();
			Field[] allFields;
			String modifier = "";
			while (theClass != null) {
				allFields = theClass.getDeclaredFields();
				for (int i = 0; i < allFields.length; i++) {
					modifier = Modifier.toString(allFields[i].getModifiers());
					if (modifier.indexOf("transient") < 0 && modifier.indexOf("final") < 0
							&& modifier.indexOf("static") < 0
					// && this.isDBFieldType(allFields[i].getType().getName())
					) {
						fields.add(allFields[i]);
					}
				}
				theClass = theClass.getSuperclass();
			}
		}
		return fields;
	}

}